<script setup lang="ts">
import { useTemplateRef, onMounted, onUnmounted, ref, provide } from 'vue'
import { heightKey } from './injectionSymbols.ts'
import { gsap } from 'gsap'

const emit = defineEmits<{
  change: [index: number]
}>()

const screenScrollRef = useTemplateRef<HTMLElement>('screenScroll')
let action = true
const height = ref(window.innerHeight + 'px')
let index = 0

//滚轮事件
const handleMouseWheel = () => {
  if (screenScrollRef.value) {
    //给页面绑定滑轮滚动事件
    screenScrollRef.value.addEventListener(
      'wheel',
      (event) => {
        event.preventDefault()
        if (action && screenScrollRef.value) {
          const innerHeight = window.innerHeight
          const scrollHeight = screenScrollRef.value.scrollHeight - innerHeight
          const currentHeight = index * innerHeight
          if (event.deltaY < 0) {
            if (currentHeight < scrollHeight) {
              action = false
              index++
              handleTween(currentHeight, index * innerHeight)
            }
          } else {
            if (index > 0) {
              action = false
              index--
              handleTween(currentHeight, index * innerHeight)
            }
          }
        }
      },
      { passive: false },
    ) // 被动监听，用于改善滚动性能
  }
}
//缓动
const handleTween = (currentLocation: number, targetLocation: number) => {
  emit('change', index)
  const coords = { x: currentLocation }
  gsap.to(coords, {
    x: targetLocation,
    duration: 1,
    ease: 'power2.inOut',
    onUpdate: () => {
      if (screenScrollRef.value) {
        screenScrollRef.value.scrollTo({
          top: coords.x as number,
          behavior: 'auto',
        })
      }
    },
    onComplete: () => {
      action = true
    },
  })
}
//滑动事件
const handleSwipe = (e: string) => {
  if (e === 'top') {
    if (screenScrollRef.value) {
      const innerHeight = window.innerHeight
      const scrollHeight = screenScrollRef.value.scrollHeight - innerHeight
      if (action) {
        const currentHeight = index * innerHeight
        if (currentHeight < scrollHeight) {
          action = false
          index++
          handleTween(currentHeight, index * innerHeight)
        }
      }
    }
  } else if (e === 'bottom') {
    if (screenScrollRef.value) {
      const innerHeight = window.innerHeight
      if (action) {
        const currentHeight = index * innerHeight
        if (index > 0) {
          action = false
          index--
          handleTween(currentHeight, index * innerHeight)
        }
      }
    }
  }
}
//滑动到指定项
const handleScrollTo = (currentIndex: number) => {
  if (screenScrollRef.value && action) {
    const oBody = screenScrollRef.value
    const currentHeight = index * window.innerHeight
    index = currentIndex
    if (oBody.scrollHeight / window.innerHeight >= index) {
      action = false
      handleTween(currentHeight, index * window.innerHeight)
    }
  }
}
//窗口变动
const handleResize = () => {
  height.value = window.innerHeight + 'px'
  if (screenScrollRef.value) {
    const scrollTop = screenScrollRef.value.scrollTop
    if (scrollTop) {
      action = false
      handleTween(scrollTop, index * window.innerHeight)
    }
  }
}

defineExpose({
  handleScrollTo,
})
provide(heightKey, height)

onMounted(() => {
  handleMouseWheel()
  window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
})
</script>

<template>
  <div
    ref="screenScroll"
    class="w-full scrollbar-hidden touch-none overflow-y-auto"
    v-touch:swipe="handleSwipe"
    :style="{ height: height }">
    <slot></slot>
  </div>
</template>
